/*
 * PlanificadorDeDisco.c
 *
 *  Created on: 30/09/2011
 *      Author: utn_so
 */

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/mman.h>
#include "libPlanificadorDeDisco.h"
#include <semaphore.h>
#include <fcntl.h>
#include "signal.h"

uint16_t cabezal;

char modoInicio[8];
char *IP;
char *puerto;
char *ID;
uint8_t algoritmo;
char *path;
uint16_t flagDeLog;
uint16_t tiempoLectura;
chs_t CHS;
uint16_t tiempoEscritura;
uint16_t RPM;
uint16_t tiempoSaltoPistas;
uint16_t i;
struct sockaddr_in *local_address;
struct sockaddr_in *remote_address;
#define MAX_BUFFER 4163
int32_t remote_client;
int32_t descriptor;
int32_t consola;
uint32_t disco;
char* ptrDisco;
t_nodo *lista;
char* sectorOcupado;
pthread_t tidPedido, tidPlanificar, tidConsola;
size_t lenDisco;
sem_t semConsola;
sem_t mutex;
t_respuesta *respuesta;
uint64_t numeroPedidos;
sem_t sem_listaPedidos;

int main(int32_t argc, char* argv[]) {
	uint32_t optval;
	uint8_t faltaHS = 1;
	uint32_t disco;
	char *args[] = { path, NULL };
	char rtaHS[20];
	lista = NULL;
	sem_init(&sem_listaPedidos, 0, 0);
	sem_init(&mutex, 0, 1);
	sem_init(&semConsola, 0, 0);
	printf("semaforos iniciados correctamente\n");
	/*printf("ingrese la ruta del archivo de configuracion: ");
	 char ruta[100];
	 fflush(stdin);
	 scanf("%s", ruta);
	 printf("\n");*/
	/*char pathDisco[100];
	 printf("ingrese la direccion del archivo disco: ");
	 fflush(stdin);
	 scanf("%s", pathDisco);
	 printf("\n");*/

	if ((disco = open("/home/utn_so/Escritorio/fat32.disk", O_RDWR)) == -1) {
		printf("\n");
		signal(SIGUSR1, senalFin);
		return EXIT_FAILURE;
	}
	printf("el archivo se abrió correctamente\n");
	lenDisco = lseek(disco, 0, SEEK_END);
	lseek(disco, 0, SEEK_SET);
	printf("tamaño del disco: %d\n", lenDisco);
	sectorOcupado = (char*) malloc(lenDisco);
	memset(sectorOcupado, 0, lenDisco);
	if ((ptrDisco = mmap(NULL, lenDisco,
			(PROT_READ | PROT_WRITE), MAP_SHARED, disco, 0))== MAP_FAILED) {
		perror("mmap()");
	}
	printf("el puntero al disco es: %s\n", ptrDisco);
	if (posix_madvise(ptrDisco, lenDisco, POSIX_MADV_SEQUENTIAL) != 0) {
		perror("posix_madvise()");
	}
	leerArchivoConfiguracion("/home/utn_so/Escritorio/prueba.txt", &modoInicio,
			&IP, &puerto, &ID, &algoritmo, &path, &flagDeLog, &tiempoLectura,
			&CHS, &tiempoEscritura, &RPM, &tiempoSaltoPistas);
	printf("%s\n", modoInicio);
	printf("%s :: %s\n", IP, puerto);
	printf("id disco: %s\n", ID);
	uint32_t addrlen = sizeof(struct sockaddr_in);
	char buffer[MAX_BUFFER];
	descriptor = (int32_t) socket(AF_INET, SOCK_STREAM, 0);
	local_address = malloc(sizeof(struct sockaddr_in));
	remote_address = malloc(sizeof(struct sockaddr_in));
	memset(buffer, '\0', MAX_BUFFER);

	local_address->sin_family = AF_INET;
	local_address->sin_addr.s_addr = inet_addr(IP);
	local_address->sin_port = htons((atoi(puerto)));

	pid_t pid = fork();
	if (pid == -1) {
		perror("fork()");
		signal(SIGUSR1, senalFin);
		return -1;
	}
	if (pid) {
		printf("proceso padre\n");

		t_correrPedido msg;
		msg.lista = lista;
		msg.descriptor = descriptor;
		msg.remote = remote_address;
		printf("a punto de entrar en el hilo pedido\n");

		if (pthread_create(&tidPlanificar, NULL, (void*) planificar,
				(void*) lista)) {
			perror("No se pudo crear el thread de planificacion");
			signal(SIGUSR1, senalFin);
			return EXIT_FAILURE;
		}

		if (pthread_create(&tidPedido, NULL, (void*) correrAtencionDePedidos,
				(void*) &msg)) {
			perror("No se pudo crear el thread de atencion de pedidos\n");
			signal(SIGUSR1, senalFin);
			return EXIT_FAILURE;
		}
		pthread_create(&tidConsola, NULL, (void*) consolar, NULL);

		printf("a punto de entrar en el hilo planificacion\n");

	} else {
		printf("proceso hijo\n");
		if (execv("/home/utn_so/Desarrollo/Workspace/Consola/Debug/Consola",
				args) == -1) {
			perror("execv()");

		}
	}
	pthread_join(tidPedido, NULL);
	pthread_join(tidPlanificar, NULL);
	pthread_join(tidConsola, NULL);
	printf("sigo ejecutando el main mientras tanto\n");
	close(descriptor);
	close(remote_client);

	return 0;

}
